package com.jdk.learn.juc._06multithreadsecurity;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by ricky
 * on 2018/1/31.
 * <p>
 * 最基本的的生产者问题复现
 * 生产者消费者问题
 * 店员
 * 使用lock同步锁和condition条件操作
 */
public class TestProductAndConsumerFullLockAndCondtion {
    public static void main(String[] args) {
        Clerk3 Clerk3 = new Clerk3();
        Product3 Product3 = new Product3(Clerk3);
        Consumer3 Consumer3 = new Consumer3(Clerk3);

        new Thread(Product3, "生产者1").start();
        new Thread(Consumer3, "消费者1").start();
//        new Thread(Product3, "生产者2").start();
//        new Thread(Consumer3, "消费者2").start();
    }
}

/**
 * 售货员
 */
class Clerk3 {
    private int Product3nums = 0;//产品数量

    private Lock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();//唤醒 等待使用

    /**
     * 拿货 取
     */
    public void get() {
        lock.lock();
        try {
            while (Product3nums >= 1) {//产品已满  用if的话可能会是负值  避免虚假唤醒的问题
                System.out.println("产品已满");
                try {
                    condition.await();//等待  不生产了
                } catch (Exception e) {
                }
            }
            System.out.println(Thread.currentThread().getName() + "-------    " + ++Product3nums);
            condition.signalAll();//唤醒
        } finally {
            lock.unlock();
        }
    }

    /**
     * 卖货
     */
    public void sale() {
        lock.lock();
        try {
            while (Product3nums <= 0) {//产品缺货
                System.out.println("产品缺货");
                try {
                    condition.await();//等待  没货了
                } catch (Exception e) {
                }
            }
            System.out.println(Thread.currentThread().getName() + "-------    " + --Product3nums);
            condition.signalAll();//唤醒
        } finally {
            lock.unlock();
        }
    }
}


/**
 * 生产者
 */
class Product3 implements Runnable {
    private Clerk3 Clerk3;

    public Product3(Clerk3 Clerk3) {
        this.Clerk3 = Clerk3;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Clerk3.get();
        }
    }
}


/**
 * 消费者
 */
class Consumer3 implements Runnable {
    private Clerk3 Clerk3;

    public Consumer3(Clerk3 Clerk3) {
        this.Clerk3 = Clerk3;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Clerk3.sale();
        }
    }
}
